#include <stdbool.h>
#include "canfestival.h"
#include "canfestival_timer.h"
#include "stm32f4xx_hal.h"
#include "rtthread.h"
#include "main.h"
#define DBG_TAG "co timer"
#define DBG_LVL DBG_LOG
#include <rtdbg.h>

#define CANFESTIVAL_TIM_HANDLE	(&htim7)
static void Canopen_Time_Thread_Entry(void* parameter);
extern rt_mutex_t pMutex_canOpen;
extern TIM_HandleTypeDef htim7;
extern void MX_TIM7_Init(void);
TIMEVAL     last_counter_val = 0;           //上次计时初值，如果发生了中断，初值就会被设置为0
TIMEVAL     elapsed_time = 0;               //距上次设定时间
struct rt_semaphore sem_canOpenTime;

static rt_thread_t tid_canopen_timer;

void Canfestival_TimerStart(void)
{
	MX_TIM7_Init();
	rt_sem_init(&sem_canOpenTime,"sem canopen time",0,RT_IPC_FLAG_FIFO);
	tid_canopen_timer = rt_thread_create(	"co timer",
												Canopen_Time_Thread_Entry,
												RT_NULL,
												CANOPEN_TIME_THREAD_STACK_SIZE,
												CANOPEN_TIME_THREAD_PRIORITY,
												CANOPEN_TIME_THREAD_TIME_SLICE);
	if(tid_canopen_timer != NULL)
	{
		rt_thread_startup(tid_canopen_timer);
	}
	HAL_TIM_Base_Start_IT(&htim7);
	
}

/********************************************
 * @brief Set a timerfor a given time.
 * @param value The time value.
 *******************************************/
//Set the timer for the next alarm.
void setTimer(TIMEVAL value)
{
  uint32_t timer = __HAL_TIM_GET_COUNTER(CANFESTIVAL_TIM_HANDLE); // Copy the value of the running timer

  elapsed_time += timer - last_counter_val;		
  last_counter_val = TIMEVAL_MAX - value;
  __HAL_TIM_SET_COUNTER(CANFESTIVAL_TIM_HANDLE, TIMEVAL_MAX - value);
//  __HAL_TIM_ENABLE_IT(CANFESTIVAL_TIM_HANDLE, TIM_IT_UPDATE);
}

/**
 * @brief Get the time elapsed since latest timer occurence.
 * @return time elapsed since latest timer occurence
 */
//Return the elapsed time to tell the Stack how much time is spent since last call.
TIMEVAL getElapsedTime(void)
{
  uint32_t timer = __HAL_TIM_GET_COUNTER(CANFESTIVAL_TIM_HANDLE);// Copy the value of the running timer

  if(timer < last_counter_val)
    timer += TIMEVAL_MAX;

  TIMEVAL elapsed = timer - last_counter_val + elapsed_time;

  return elapsed;
}

static void Canopen_Time_Thread_Entry(void* parameter)
{
	while(1)
	{
		if(rt_sem_take(&sem_canOpenTime,RT_WAITING_FOREVER) != RT_EOK)
		{
			 LOG_E("canfestival take timer sem failed");
		};
		rt_mutex_take(pMutex_canOpen,RT_WAITING_FOREVER);
		TimeDispatch();
		rt_mutex_release(pMutex_canOpen);
	}
}

